% 双端队列（Deque）类，继承自handle类（句柄对象，支持引用传递）
classdef Deque < handle
    % 公共属性（可直接访问）
    properties
        InitialSize  % 队列的初始大小（缓冲区初始容量）
        FixedSize = false  % 是否启用固定大小模式（默认不启用）
    end

    % 私有属性（仅类内部方法可访问）
    properties(Access = private)
        pBuffer  % 存储队列数据的缓冲区（数值数组）
        Num      % 每个元素的维度（例如：Num=2表示每个元素是2维向量）
    end

    % 公共方法（外部可调用的接口）
    methods(Access = public)
        % 构造函数：初始化双端队列
        % Inputs:
        %   InitialSize - 初始缓冲区大小（行数）
        %   FixedSize   - 是否固定缓冲区大小（true/false）
        %   Num         - 每个元素的维度（列数）
        function obj = Deque(InitialSize, FixedSize, Num)
            obj.InitialSize = InitialSize;  % 初始化初始大小
            obj.FixedSize = FixedSize;      % 初始化固定大小模式
            obj.Num = Num;                  % 初始化元素维度
            obj.reset();  % 调用重置方法，初始化缓冲区
        end
        
        % 返回当前队列的大小（缓冲区中的元素数量，即行数）
        function len = size(obj)
            len = length(obj.pBuffer);
        end

        % 从队列尾部（后端）添加元素
        % Input:
        %   u - 待添加的元素（可以是单个元素或批量元素，需与Num维度匹配）
        function push_back(obj, u)
            % 将元素添加到缓冲区尾部（通过数组拼接实现）
            obj.pBuffer = [obj.pBuffer; u];
            % 若启用固定大小模式，删除头部超出容量的旧元素
            if obj.FixedSize
                % 保留尾部与初始大小相等的元素，删除头部多余元素
                obj.pBuffer(1 : length(u), :) = [];
            end
        end

        % 从队列头部（前端）添加元素
        % Input:
        %   u - 待添加的元素（可以是单个元素或批量元素，需与Num维度匹配）
        function push_front(obj, u)
            % 将元素添加到缓冲区头部（通过数组拼接实现）
            obj.pBuffer = [u; obj.pBuffer];
            % 若启用固定大小模式，删除尾部超出容量的旧元素
            if obj.FixedSize
                % 保留头部与初始大小相等的元素，删除尾部多余元素
                obj.pBuffer(end - length(u) + 1 : end) = [];
            end
        end

        % 从队列尾部（后端）移除并返回元素
        % Input:
        %   n - 要移除的元素数量
        % Output:
        %   u - 移除的元素（若n大于当前元素数，不足部分用0填充）
        function u = pop_back(obj, n)
            % 若要移除的数量小于等于当前元素数
            if n <= length(obj.pBuffer)
                % 提取尾部n个元素
                u = obj.pBuffer(end - n + 1 : end, :);
                % 从缓冲区中删除尾部n个元素
                obj.pBuffer(end - n + 1 : end, :) = [];
                % 若启用固定大小模式，在头部补n个0元素以保持容量
                if obj.FixedSize
                    obj.pBuffer = [zeros(n, obj.Num); obj.pBuffer];   
                end
            else
                % 若要移除的数量大于当前元素数，不足部分用0填充
                u = [zeros(n - length(obj.pBuffer), obj.Num); obj.pBuffer];
                % 若启用固定大小模式，缓冲区填充0；否则清空缓冲区
                if obj.FixedSize
                    obj.pBuffer(:) = 0;
                else
                    obj.pBuffer = [];
                end
            end
        end

        % 从队列头部（前端）移除并返回元素
        % Input:
        %   n - 要移除的元素数量
        % Output:
        %   u - 移除的元素（若n大于当前元素数，不足部分用0填充）
        function u = pop_front(obj, n)
            % 若要移除的数量小于等于当前元素数
            if n <= length(obj.pBuffer)
                % 提取头部n个元素
                u = obj.pBuffer(1 : n, :);
                % 从缓冲区中删除头部n个元素
                obj.pBuffer(1 : n, :) = [];
                % 若启用固定大小模式，在尾部补n个0元素以保持容量
                if obj.FixedSize
                    obj.pBuffer = [obj.pBuffer; zeros(n, obj.Num)];              
                end
            else
                % 若要移除的数量大于当前元素数，不足部分用0填充
                u = [obj.pBuffer; zeros(n - length(obj.pBuffer), obj.Num)];
                % 若启用固定大小模式，缓冲区填充0；否则清空缓冲区
                if obj.FixedSize
                    obj.pBuffer(:) = 0;
                else
                    obj.pBuffer = [];
                end
            end
        end

        % 重置队列：将缓冲区恢复为初始大小的零矩阵
        function reset(obj)
            obj.pBuffer = zeros(obj.InitialSize, obj.Num);
        end
    end
end